package main

import (
	"context"
	"fmt"
	"log"
	"os"
	"path/filepath"
	"sort"
	"strconv"

	"fyne.io/fyne"
	"fyne.io/fyne/app"
	"fyne.io/fyne/widget"
)

type AppGui struct {
	out        *widget.Entry
	app        fyne.App
	window     fyne.Window
	recFile    *widget.Entry
	actionFile *widget.SelectEntry
	count      *widget.Entry
	rec, play  *widget.Button
	console    *widget.ScrollContainer
	ctx        context.Context
}

type IGui interface {
	Println(some string)
	Printf(f string, args ...interface{})
	OnEnd()
	Context() context.Context
	MakeRecordPath(fn string) string
}

func NewAppGui() *AppGui {
	return &AppGui{out: widget.NewMultiLineEntry(), app: app.New(), count: widget.NewEntry()}
}

func (s *AppGui) Show() {
	ctx, cancel := context.WithCancel(context.Background())
	s.ctx = ctx

	w := s.app.NewWindow("MouseGo")

	s.window = w

	s.out.SetReadOnly(true)
	console := widget.NewVScrollContainer(s.out)
	s.console = console
	console.SetMinSize(fyne.NewSize(480, 320))
	console.Show()

	gr1 := s.createRecordFileGroup()
	s.rec = widget.NewButton("记录动作", func() {
		s.play.Disable()
		s.rec.Disable()
		record(s.recFile.Text, s)

	})

	gr2 := s.createActionFileGroup()
	s.count.SetText("99999")
	cg := s.createCountGroup()
	s.play = widget.NewButton("执行动作", func() {

		go func() {
			s.play.Disable()
			s.rec.Disable()
			c, err := strconv.Atoi(s.count.Text)
			if err != nil {
				log.Println(err)
			}
			go play(s.actionFile.Text, c, s)

		}()
	})

	w.SetContent(widget.NewVBox(
		gr1,
		s.rec,
		gr2,
		cg,
		s.play,
		console,
		widget.NewButton("Quit", func() {
			s.app.Quit()
		}),
	))

	w.ShowAndRun()
	cancel()
}

func (s *AppGui) Println(some string) {
	s.out.SetText(s.out.Text + "\n" + some)
	s.scroll()
}

func (s *AppGui) Printf(f string, args ...interface{}) {
	s.out.SetText(s.out.Text + "\n" + fmt.Sprintf(f, args...))
	s.scroll()
}

func (s *AppGui) Quit() {
	s.app.Quit()
}

func (s *AppGui) getRecordPath() string {
	exe1, err := os.Executable()
	if err != nil {
		log.Println(err.Error())
		return ""
	}
	res := filepath.Join(filepath.Dir(exe1), "records")
	os.MkdirAll(res, os.ModePerm)
	return res
}

func (s *AppGui) MakeRecordPath(fn string) string {
	return filepath.Join(s.getRecordPath(), fn)
}

//func(fyne.URIReadCloser, error)
func (s *AppGui) setRecordFile(uri fyne.URIReadCloser, err error) {
	if err != nil {
		log.Println(err)
	} else if uri != nil {
		s.recFile.SetText(uri.Name())
	}
}

func (s *AppGui) setActionFile(uri fyne.URIReadCloser, err error) {
	if err != nil {
		log.Println(err)
	} else if uri != nil {
		s.actionFile.SetText(uri.Name())
	}
}

func (s *AppGui) createRecordFileGroup() *widget.Box {
	s.recFile = widget.NewEntry()
	s.recFile.SetText("default")
	return widget.NewHBox(
		widget.NewLabel("保存到文件："),
		s.recFile)
}

func (s *AppGui) createActionFileGroup() *widget.Box {
	fp, err := os.Open(s.getRecordPath())
	if err != nil {
		panic(err)
	}
	defer fp.Close()
	dirs, err := fp.Readdirnames(0)
	if err != nil {
		panic(err)
	}
	sort.Strings(dirs)
	s.actionFile = widget.NewSelectEntry(dirs)
	s.actionFile.SetText("default")
	return widget.NewHBox(
		widget.NewLabel("执行该文件："),
		s.actionFile)
}

func (s *AppGui) createCountGroup() *widget.Box {
	return widget.NewHBox(
		widget.NewLabel("循环次数："),
		s.count)
}

func (s *AppGui) OnEnd() {
	s.rec.Enable()
	s.play.Enable()
}

func (s *AppGui) scroll() {
	if s.out.Size().Height > 320 {
		s.console.Offset = fyne.NewPos(0, s.out.Size().Height-300)
	}

}

func (s *AppGui) Context() context.Context {
	return s.ctx
}
